<?

class Page_tree extends PHLARE_Model
{
	
    public function __construct()
	{
		parent::__construct();
		
		$db_fields = array(
			'id' => new Auto_field(
				array(
					'field_name' => 'id'
				)
			),
			'object_id' => new Integer_field(
				array(
					'field_name' => 'page_id',
					'unsigned' => true,
					'index' => true
				)
			),
			'object_version' => new Integer_field(
				array(
					'field_name' => 'object_version',
					'unsigned' => true,
					'index' => true
				)
			),
			'object_class' => new Char_field(
				array(
					'field_name' => 'class'
				)
			),
			'parent_id' => new Integer_field(
				array(
					'field_name' => 'parent_id',
					'unsigned' => true,
					'index' => true
				)
			),
			'left_val' => new Integer_field(
				array(
					'field_name' => 'left_val',
					'unsigned' => true,
					'index' => true
				)
			),
			'right_val' => new Integer_field(
				array(
					'field_name' => 'right_val',
					'unsigned' => true,
					'index' => true
				)
			),
			'stage_state' => new Collection_field(
				array(
					'field_name' => 'stage_state',
					'data_values' => array(	// options
						'stage' => 'Stage',
						'live' => 'Live',
						'history' => 'History'
					),
					'default_value' => 'stage'
				)
			)
		);
		
		$this->initialize_db_fields($db_fields);
	} // end __construct
	
	protected function on_after_create()
	{
		// Create views
		$this->recreate_views();
		
		// Add the home page
		$query = $this->db->query("
			INSERT INTO `" . $this->db->dbprefix . $this->db_table . "` (
				`object_id`,
				`object_version`,
				`object_class`,
				`parent_id`,
				`left_val`,
				`right_val`,
				`stage_state`
			)
			VALUES
			(
				'1', '1', 'Page', '0', '1', '8', 'stage'
			),
			(
				'2', '1', 'Page', '1', '2', '3', 'stage'
			),
			(
				'3', '1', 'Page', '1', '4', '7', 'stage'
			),
			(
				'4', '1', 'Page', '3', '5', '6', 'stage'
			)
		");
	} // end on_after_create
	
	protected function on_after_update()
	{
		// Update views, in case the original table definition has changed
		$this->recreate_views();
	} // end on_after_update
	
	
	/**
	 * recreate_views:
	 * Every time the table definition changes, we need to recreate the views. MySQL makes that easy.
	 * 
	 * @return null
	 */
	protected function recreate_views()
	{
		// Create the "Live" view
		$query = $this->db->query('CREATE OR REPLACE VIEW `' . $this->db->dbprefix . $this->db_table . '_live` AS
		SELECT * FROM `' . $this->db->dbprefix . $this->db_table . '` WHERE `stage_state`="live"');
		
		// Create the "Stage" view
		$query = $this->db->query('CREATE OR REPLACE VIEW `' . $this->db->dbprefix . $this->db_table . '_stage` AS
		SELECT * FROM `' . $this->db->dbprefix . $this->db_table . '` WHERE `stage_state`="stage"');
	} // end recreate_views
	
	
	public function get_page_tree_stage($parent_id = 'root')
	{
		return $this->get_page_tree('_stage', $parent_id);
	} // end get_page_tree_stage
	
	public function get_page_tree_live($parent_id = 'root')
	{
		return $this->get_page_tree('_live', $parent_id);
	} // end get_page_tree_live
	
	private function get_page_tree($view = '_live', $parent_id = 'root')
	{
		$tree = array();
		
		if($parent_id === 'root')
		{
			$parent_id = $this->get_site_root();
		}
		
		if($parent_id !== false)
		{
			// Get the parent
			$parent_query = $this->db->get_where(
				$this->db_table . $view,
				array('id' => $parent_id)
			);
			
			if($parent_query->num_rows())
			{
				$parent = $parent_query->row(); // Should only be one
				
				// Get the parent and all it's children
				$this->db->order_by('left_val', 'ASC');
				$query = $this->db->get_where(
					$this->db_table . $view,
					array(
						'left_val >=' => $parent->left_val
					)
				);
				
				if($query->num_rows())
				{
					foreach($query->result() as $row)
					{
						$temp = new $row->object_class(
							$row->object_id,
							$row->object_version,
							$row->parent_id,
							$row->left_val,
							$row->right_val,
							$row->stage_state
						);
						
						$tree[] = $temp;
						
						unset($temp);
					}
				}
			}
		}
		
		return $tree;
	} // end get_page_tree
	
	
	public function get_site_root()
	{
		$query = $this->db->get_where(
			$this->db_table,
			array('parent_id' => 0)
		);
		if($query->num_rows())
		{
			$row = $query->row();
			return $row->id;
		}
		else
		{
			return false;
		}
	} // end get_site_root
	
	
	public function rebuild_tree($id, $left)
	{
		// the right value of this node is the left value + 1
		$right = $left+1;
		
		// get all children of this node
		$query = $this->db->get_where(
			$this->db_table,
			array('parent_id' => $id)
		);
		
		foreach ($query->result() as $row)
		{
			// Recursive execution of this function for each child of this node.
			// $right is the current right value, which is incremented by the rebuild_tree function.
			$right = $this->rebuild_tree($row->id, $right);
		}
		
		// we've got the left value, and now that we've processed
		// the children of this node we also know the right value
		$data = array(
			'left_val' => $left,
			'right_val' => $right
		);
		$this->db->where('id', $id);
		$this->db->update($this->db_table, $data); 
		
		// return the right value of this node + 1
		return $right+1;
	} // end rebuild_tree
	
	
	public function get_page_tree_row($object_class, $object_id, $object_version)
	{
		$this->db->where('object_class', $object_class);
		$this->db->where('object_id', $object_id);
		$this->db->where('object_version', $object_version);
		$this->db->where('stage_state', 'stage');
		
		$query = $this->db->get($this->db_table);
		return $query->row();
	} // end get_page_tree_row
	
	
	public function new_page_tree_row(
		$object_id,
		$object_version,
		$object_class,
		$parent_id,
		$left_val,
		$right_val,
		$stage_state
	)
	{
		$data = array(
			'object_id' => $object_id,
			'object_version' => $object_version,
			'object_class' => $object_class,
			'parent_id' => $parent_id,
			'left_val' => $left_val,
			'right_val' => $right_val,
			'stage_state' => $stage_state
		);
		$this->db->insert($this->db_table, $data);
	} // end new_page_tree_row
	
	
	public function stage_to_history($object_class, $object_id)
	{
		$this->db->where('object_class', $object_class);
		$this->db->where('object_id', $object_id);
		$this->db->where('stage_state', 'stage');
		
		$this->db->update(
			$this->db_table,
			array(
				'stage_state' => 'history'
			)
		);
		
		return $this->db->affected_rows();
	} // end stage_to_history
    
} // end Page